/*
 * @Author: 台阶
 * @Date: 2020-05-21 10:32:08
 * @LastEditTime: 2020-05-25 22:22:08
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \jump\assets\script\game\stage\Stage.ts
 */ 

import { Player } from "./Player";
import { Block } from "./Block";
import { G } from "../../G";
import { PlayerDieEvent } from "../../events/PlayerDieEvent";
import { PlayerJumpSuccessEvent } from "../../events/PlayerJumpSuccessEvent";

const {ccclass, property} = cc._decorator;

@ccclass
export class Stage extends cc.Component {

    @property(Player)
    private player: Player = null;
    
    @property(cc.Vec2)
    public leftOrigin: cc.Vec2 = cc.v2();
    @property(cc.Vec2)
    public rightOrigin: cc.Vec2 = cc.v2();
    @property(cc.Node)
    public blockLayer: cc.Node = null;
    @property(cc.Float)
    public arrayRatio: number = 0.556047197640118;
    @property([cc.Prefab])
    private blockList: Array<cc.Prefab> = [];

    private currBlock: Block = null;

    private nextBlock: Block = null;

    // 初始化 台阶
    public reset() {
        this.blockLayer.removeAllChildren();

        // 添加第一个小方块
        let blockNode = cc.instantiate(this.blockList[0]);
        this.blockLayer.addChild(blockNode);
        let block = blockNode.getComponent(Block); 
        // 设置方块初始化位置，默认左初始位
        // stage 和 player 在同级节点下
        blockNode.setPosition(this.blockLayer.parent.convertToNodeSpaceAR(this.leftOrigin));

        // 第一块方块
        this.currBlock = block;
        this.nextBlock = block;

        // 设置玩家位置为第一块中心
        this.player.node.setPosition(this.node.parent.convertToNodeSpaceAR(this.currBlock.getCenterPosition()));

        this.addBlock();
    }

    public addBlock() {
        // 随机添加一个类型的方块
        let n = Math.floor(Math.random() * this.blockList.length);
        let blockNode = cc.instantiate(this.blockList[n]);
        this.blockLayer.addChild(blockNode);

        let block = blockNode.getComponent(Block);
        let scale = block.minScale + Math.random() * (block.maxScale - block.minScale);
        // 随机间隔距离
        let distance = block.minDistance + Math.random() * (block.maxDistance - block.minDistance);
        // 方块缩放大小
        blockNode.scale = scale;
        // 判断角色朝向
        if (this.player.direction > 0) {
            // 设置新添加的方块位置
            blockNode.x = this.currBlock.node.x + distance;
            blockNode.y = this.currBlock.node.y + distance * this.arrayRatio;
        } else {
            blockNode.x = this.currBlock.node.x - distance;
            blockNode.y = this.currBlock.node.y + distance * this.arrayRatio;
        }
        this.currBlock = this.nextBlock;
        this.nextBlock = block;
        return block;
    }

    // 游戏开始，添加监听
    public enableTouch () {
        cc.find("Canvas").on(cc.Node.EventType.TOUCH_START, this.onReadyJump, this);
        cc.find("Canvas").on(cc.Node.EventType.TOUCH_END, this.onJump, this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this);
    }

    // 游戏结束，移除监听
    public disableTouch() {
        cc.find("Canvas").targetOff(this);
        cc.systemEvent.targetOff(this);
    }

    // 回调：触摸开始
    public onReadyJump () {
        this.player.readyJump();

    }

    // 回调：触摸结束 
    public onJump () {
        // 玩家蓄力距离
        let jumpDistance = this.player.jumpDistance;
        // 玩家方向
        let dir = this.player.direction;

        let targetPos = cc.v2(this.player.node.x + jumpDistance * dir, this.player.node.y + jumpDistance * this.arrayRatio);
        let targetWorldPos = this.player.node.parent.convertToWorldSpaceAR(targetPos);
        // 拿到 与目标距离最近的方块锚点坐标
        let formatPos = this.nextBlock.getAnchorLocation(targetWorldPos, dir);

        if (formatPos !== null) {
            this.player.jumpTo(formatPos, ()=>{
                this.currBlock = this.nextBlock;
                // 得分动画
                this.currBlock.playScoreAnim();
                // 发送跳跃成功事件，--》方块分数
                G.dispatchEvent(new PlayerJumpSuccessEvent(this.currBlock.score));
            });
        } else {
            this.player.jumpTo(targetWorldPos, ()=>{
                G.dispatchEvent(new PlayerDieEvent());
            });
        }
    }

    // 回调：键盘空格开始
    private onKeyDown (event) {
        if (event.keyCode === cc.macro.KEY.space) {
            this.onReadyJump();
        }
    }

    // 回调：键盘空格结束
    private onKeyUp (event) {
        if (event.keyCode === cc.macro.KEY.space) {
            this.onJump();
        }
    }

    // 判断是否落到方块上
    public checkOver(): boolean {
        let vec = cc.v2(this.player.node.x, this.player.node.y).sub(cc.v2(this.currBlock.node.x, this.currBlock.node.y));
        let dis = vec.mag();
        let border = this.currBlock.node.width / 2 * this.currBlock.node.scale;

        return dis > border;
    }

    // 更新台阶位置 当前位置 移动到 左右初始位置
    public updateStage(cb: Function, cbTarget?: any) {
        let moveVector;
        let playerWorldPos = this.player.node.parent.convertToWorldSpaceAR(this.player.node.position);
        // 计算当前玩家与初始位置 差值
        if (this.player.direction > 0) {
            moveVector = cc.v2(playerWorldPos.x, playerWorldPos.y).sub(this.leftOrigin);
        } else {
            moveVector = cc.v2(playerWorldPos.x, playerWorldPos.y).sub(this.rightOrigin);
        }
        // 移动stage节点
        cc.tween(this.node)
            .to(0.5, {position: cc.v2(this.node.x, this.node.y).sub(moveVector)})
            .call(()=>{
                cb();
            })
            .start();
    }
}